home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
076-100
/
disk_079
/
sharedlib
/
library.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
7KB
|
258 lines
/* Library.c
* Routines required in all shared libraries.
* Copyright 1986 by James M Synge.
*/
#include "exec/types.h"
#include "exec/libraries.h"
#include "ExtLibrary.h"
#include "libraries/dos.h"
/* Declare the name of the library */
char LibraryName[] = "task.library";
char LibraryId[] =
"task.library V1.0 (25 May 1987)\015\012";
#define LIB_VERSION 1
#define LIB_REVISION 2
/*
* This short assembler section is included here so that
* there is just one small place where these numbers need to
* be replaced, instead of in two different files (i.e. here
* and LibHead.asm).
*/
#asm
PUBLIC LibVersion
PUBLIC LibRevision
LibVersion EQU 1 ; Shared with libhead via
LibRevision EQU 2 ; the PUBLIC statement
#endasm
/*
* If the rt_Flags field of the RomTag (struct Resident) has
* the AUTOINIT bit set, then the rt_Init field must point
* to a block such the following LibInitBlock. This block
* contains four of the five parameters which OpenLibrary()
* will pass to MakeLibrary. (The fifth parameter is the
* SegList.) If the AUTOINIT bit is not set, then the
* rt_Init field must point to a routine which will perform
* the equivalent initialization.
*
* When the library is being auto-initialized, a block of
* memory is allocated by MakeLibrary(). Its size is
* determined by the length of FunctionList (in Functions.c)
* and an entry, lib_sizeof_ExtLibrary, in the structure
* pointed to by rt_Init. That entry is the size in bytes
* of the struct ExtLibrary to be allocated automatically,
* before calling the routine whose address is in
* lib_InitCode. So, this value must be known before
* linking.
*
* This can be done by expressing the LibInitBlock structure
* in C so that the compiler can determine the size for us.
* This is a drastic improvement over figuring it out by
* hand!
*/
extern long *FunctionList[];
void _LibInitCode();
struct {
long lib_sizeof_ExtLibrary; /* Bytes to allocate */
APTR lib_FunctionList; /* Ptr to func list */
long lib_InitStruct; /* see initializers.i */
APTR lib_InitCode; /* Ptr to asm routine */
} LibInitBlock = {
sizeof( struct ExtLibrary ),
(APTR) FunctionList,
0L, /* No struct init */
(APTR) _LibInitCode
};
/* The assembly routine _LibInitCode calls LibraryInit() to
* complete the initialization of the library.
*/
struct ExtLibrary *
LibraryInit( LibBasePtr )
struct ExtLibrary *LibBasePtr;
{
/* These initializations are done here because it is
* difficult to build an initializer structure with
* Aztec Assembler 3.2. The argument, the library
* pointer, is pushed onto the stack by the
* assembler routine _LibInitCode.
*/
LibBasePtr -> el_Node.ln_Type = NT_LIBRARY;
LibBasePtr -> el_Node.ln_Name = LibraryName;
LibBasePtr -> el_Version = LIB_VERSION;
LibBasePtr -> el_Revision = LIB_REVISION;
LibBasePtr -> el_IdString = (APTR) LibraryId;
/* Now set up the initial values for my libraries'
* variables.
*/
/* NONE IN THIS EXAMPLE!!! */
return LibBasePtr; /* This is the value which
* will be returned to
* MakeLibrary()
*/
}
/*
* The required routines Open, Close and Expunge are called
* not by other C routines, but rather by Exec. This means
* that their arguments are in registers instead of on the
* stack.
*
* There are three straight forward options at this point:
*
* 1) Use the variable LibraryBase (see LibHead.asm) which
* should contain the same value as that in A6.
*
* 2) Immediately call the routine regA6() in LibHead.asm
* which will return the value in A6 (Should be the
* Library Base Pointer). This requires that we can be
* certain that A6 hasn't been wiped out already by the
* compiler generated setup code.
*
* 3) Place an intermediate assembly routine between exec
* and each C routine which moves the arguments,
* including the Library Base Pointer, from the
* registers to the stack.
*
* The last method seems the best, so we'll use it.
*/
struct ExtLibrary *
Library_Open( LibBasePtr, Version )
struct ExtLibrary *LibBasePtr; /* Was in A6 */
long Version; /* Was in D0 */
{
Forbid();
/* Note that another open has occured. */
LibBasePtr->el_OpenCnt ++;
/* Since we know that there is at least one user of
* this library, we'll ignore any previous call to
* Library_Expunge.
*/
LibBasePtr->el_Flags &= ~LIBF_DELEXP;
Permit();
return LibBasePtr;
}
/* When the memory allocator in exec.library is looking for
* more memory, it will try to get rid of the memory used by
* libraries, devices and fonts. To do this with a library,
* it calls Library_Expunge, the third of the required
* routines. If Library_Expunge returns zero, then the
* memory allocator looks elsewhere. If it returns non-zero
* then the value must be a pointer to an AmigaDOS SegList.
* This will be placed on the free list by the memory
* allocator. It is the responsibility of the library to
* free the jump table and Library structure.
*/
extern BPTR LibSegList; /* Allocated in LibHead.asm */
BPTR
Library_Expunge( LibBasePtr )
struct ExtLibrary * LibBasePtr; /* Was in A6 */
{
unsigned long size, JumpTableBase;
/* The memory allocator runs inside a Forbid() /
* Permit() pair. To protect against being called
* by somebody else (i.e. Library_Close).
*/
Forbid ();
if (LibBasePtr->el_OpenCnt > 0) {
/* Still open, so note the expunge for
* later use in Library_Close.
*/
LibBasePtr->el_Flags |= LIBF_DELEXP;
Permit ();
return 0;
}
/* Remove the library from the exec library list
* so that nobody tries to allocate the library.
*/
Remove( LibBasePtr );
/* Now free up the jump table and library structure.
* We add the sizes of the two (lib_NegSize is the
* size of the jump table, and lib_PosSize is the
* size of struct ExtLibrary), then free the block
* starting at the base of the jump table.
*/
size = (long)(LibBasePtr->el_NegSize)
+ (long)(LibBasePtr->el_PosSize);
if ( size ) {
JumpTableBase = (long) LibBasePtr -
(long) (LibBasePtr->el_NegSize);
FreeMem( JumpTableBase, size );
}
Permit();
return LibSegList;
}
/* When the exec routine CloseLibrary() is called, it calls
* the required Close() routine of the identified library.
* That routine is implemented here by Library_Close. It
* decrements the open count. If it is zero, and if the
* delayed expunge flags is set, then Library_Expunge() is
* called. Just as in the case of the Expunge routine, if
* a non-zero value is returned, it must be a BPTR to an
* AmigaDOS SegList.
*/
BPTR
Library_Close( LibBasePtr )
struct ExtLibrary * LibBasePtr; /* Was in A6 */
{
Forbid(); /* Have to be cautious when there's
* not much documentation. */
LibBasePtr->el_OpenCnt -- ; /* Decrement */
Permit();
if (LibBasePtr->el_OpenCnt == 0)
if ((LibBasePtr->el_Flags & LIBF_DELEXP) != 0)
return Library_Expunge();
return 0; /* No expunge. */
}
/* Now for the big routine!
*/
long Library_Reserved()
{
return(0L);
}